package com.zhang.es.service.impl;

import com.zhang.es.common.model.ProductDO;
import com.zhang.es.service.IProductRepositoryService;
import com.zhang.es.dao.ProductRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * description
 *
 * @author zhangFanJun
 * @date 2024-04-02 11:53
 **/
@RequiredArgsConstructor
@Service
@Slf4j
public class ProductRepositoryService implements IProductRepositoryService {

    private final ProductRepository productRepository;
    private final ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 测试保存，查找，删除
     */
    @Override
    public void crud() {

        ProductDO one = new ProductDO();
        one.setId(UUID.randomUUID().toString());
        one.setUserId(5566L+ ThreadLocalRandom.current().nextInt(99));
        one.setName("张三");
        one.setDescription("张三是个好人" + DateFormatUtils.format(new Date(), "yyyy/MM/dd HH:mm:ss"));
        one.setCreateTime(new Date());
        ProductDO save = productRepository.save(one);
        ProductDO productDO = productRepository.findById(save.getId()).orElse(null);
        if (Objects.nonNull(productDO)) {
            log.info("查找保存的数据productDO:{}", productDO);
            productRepository.deleteById(save.getId());
            ProductDO again = productRepository.findById(save.getId()).orElse(null);
            if(Objects.isNull(again)){
                log.info("删除后无法查找到数据");
            } else {
                log.info("删除后查找到数据：{}",again);
            }
        } else {
            log.info("无法查找到保存的数据");
        }

        productRepository.save(one);
    }

    @Override
    public PageImpl<ProductDO> find() {

        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // 内容匹配
        handleSearchContent(builder);
        // 字段条件
        builder.must(getAllFilter());

        nativeSearchQueryBuilder.withFilter(builder);
        nativeSearchQueryBuilder.withQuery(builder);

        if (false) {
            handleSort(nativeSearchQueryBuilder);
        } else {
            handleSortPage(nativeSearchQueryBuilder);
        }

        // ElasticsearchRepository不再支持复杂查找，比如 productRepository.search(nativeSearchQueryBuilder.build());
        SearchHits<ProductDO> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), ProductDO.class);

        PageRequest pageRequest = PageRequest.of(0, 20);
        if (searchHits.getTotalHits() <= 0) {
            return new PageImpl<ProductDO>(Collections.emptyList(), pageRequest, 0);
        }
        List<ProductDO> searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
        log.info("查找的结果：{}",searchProductList);

        return new PageImpl<>(searchProductList, pageRequest, searchHits.getTotalHits());
    }

    public void handleSearchContent(BoolQueryBuilder builder) {

        BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
        keywordQuery.should(QueryBuilders.termQuery("description", "好人").boost(520));
        keywordQuery.should(QueryBuilders.matchQuery("description", "好人").boost(510));
        keywordQuery.should(QueryBuilders.matchPhraseQuery("description", "好人").boost(500));
        builder.must(keywordQuery);
    }

    public BoolQueryBuilder getAllFilter() {

        BoolQueryBuilder filterBuilder = QueryBuilders.boolQuery();
        filterBuilder.should(QueryBuilders.termQuery("name","张三"))
                .minimumShouldMatch(1);
//        filterBuilder.must(new MatchQueryBuilder("id", String.join(",", Arrays.asList("1"))));

        return filterBuilder;
    }

    public static void handleSort(NativeSearchQueryBuilder nativeSearchQueryBuilder) {

        String fieldSort = "createTime";
        FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort(fieldSort).order(SortOrder.DESC);

        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 10000));
        nativeSearchQueryBuilder.withSort(fieldSortBuilder);
    }

    /**
     * 处理排序和分页
     *
     * @param nativeSearchQueryBuilder es搜索
     * @author zfj
     * @date 2023/3/8
     */
    public static void handleSortPage(NativeSearchQueryBuilder nativeSearchQueryBuilder) {

        String fieldSort = "createTime";
        FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort(fieldSort).order(SortOrder.DESC);

        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 10000));
        nativeSearchQueryBuilder.withSort(fieldSortBuilder);

        // 分页
        PageRequest pageRequest = PageRequest.of(0, 20);
        nativeSearchQueryBuilder.withPageable(pageRequest);
        nativeSearchQueryBuilder.withSort(fieldSortBuilder);
    }
}
